﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Threading;

namespace WindowsFormsApplication1
{
    class EcgDetalhe
    {
        private FormPrincipal form;
        private int[] amostrasDetalhada = new int[9 * 960]; //Armazena no máximo 9s de dados
        private int[] amostrasDetalhadaFiltrada = new int[9 * 960];
        private int[] amostrasDetalhadaPotenciaTardios = new int[9 * 960];
        private int[] amostrasDetalhadaPotenciaTardiosImg = new int[9 * 960];
        private static int tamanhoMaximoDetalhe = 9 * 960;
        private int tamanhoDetalhe = 3 * 960; //Dados impresso. No máximo 3s
        private double ganhoDetalhe = 1;
        private int[] parametros = new int[9];
        private PictureBox[] pctbxGrupoParametros = new PictureBox[9];
        private int amostrasPorSeg = 960;

        //filtros
        private double[] entradaFiltro = new double[9 * 960]; //armazenamento para manuzeio dos filtros
        private double[] saidaFiltro = new double[9 * 960];
        private double[] senoidinhaRuidosa = new double[9 * 960]; //senoide inicial = sinal bruto - media caminhante de 16 (filtro 60HZ)
        private double[] senoidinha60 = new double[9 * 960];
        private double[] senoidinha120 = new double[9 * 960];
        private double[] senoidinha180 = new double[9 * 960];
        private double[] senoidinha60eHarm = new double[9 * 960];
        
        private String[] nomeParametros = new String[9];

        private double[] A60 = new double[32];   //coeficientes do filtro 60hz
        private double[] B60 = new double[32];   //coeficientes do filtro 60hz

		private Bdac bdac = new Bdac();
		private List<BeatParameters> listaParametros= new List<BeatParameters>();
		private int[] referencia;
		
		
        public void setAmostrasDetalhada(int[] amostrasDetalhadaCompleta)
        {
            //Seta tamanho detalhe para 3 s
            tamanhoDetalhe = 3 * 960;
            //Posição do Scroll
            form.hscrbrRF.Value = 2880;
            ganhoDetalhe = 1;
            
            form.rdbtnSemFiltragem.Checked = true;
            form.rdbtn3seg.Checked = true;
            form.rdbtn33mm.Checked = true;

            //Copia a amostra para amostras auxiliares
            for (int i = 0; i < 9*960; i++)
            {
                amostrasDetalhada[i] = amostrasDetalhadaCompleta[i];
                amostrasDetalhadaFiltrada[i] = amostrasDetalhadaCompleta[i];
                amostrasDetalhadaPotenciaTardios[i] = amostrasDetalhadaCompleta[i];
            }
        }

        public void setForm(FormPrincipal form)
        {
            this.form = form;
            //Coloca todos os parametros em um array para facilitar os algoritmos
            pctbxGrupoParametros[0] = form.pctbxParametros0;
            pctbxGrupoParametros[1] = form.pctbxParametros1;
            pctbxGrupoParametros[2] = form.pctbxParametros2;
            pctbxGrupoParametros[3] = form.pctbxParametros3;
            pctbxGrupoParametros[4] = form.pctbxParametros4;
            pctbxGrupoParametros[5] = form.pctbxParametros5;
            pctbxGrupoParametros[6] = form.pctbxParametros6;
            pctbxGrupoParametros[7] = form.pctbxParametros7;
            pctbxGrupoParametros[8] = form.pctbxParametros8;
            
            //Armazena o nome de cada parametro
            nomeParametros[0] = "Início da Onda P";
            nomeParametros[1] = "Final da Onda P";
            nomeParametros[2] = "Início da Onda QRS";
            nomeParametros[3] = "Ápice da Onda R";
            nomeParametros[4] = "Final da Onda QRS";
            nomeParametros[5] = "Ponto J";
            nomeParametros[6] = "Início da Onda T";
            nomeParametros[7] = "Final da Onda T";
            nomeParametros[8] = "Ápice da R Subsequente";
        }

        public FormPrincipal getForm()
        {
            return form;
        }

        public void inicializarTab() { 
        }

        //Função para limpar as marcações
        public void limparMarcacoes() {
            for (int i = 0; i < 9; i++) {
                parametros[i] = 0;
            }
            this.plotaDetalhes();
        }

        //Função para sair do modo de marcações
        public void sairModoMarcacao() {
            form.rdbtnInicioOndaP.Checked = false;
            form.rdbtnFimOndaP.Checked = false;
            form.rdbtnInicioOndaQRS.Checked = false;
            form.rdbtnApiceOndaR.Checked = false;
            form.rdbtnFimOndaQRS.Checked = false;
            form.rdbtnInicioOndaT.Checked = false;
            form.rdbtnApiceR.Checked = false;
            form.rdbtnFimOndaT.Checked = false;
            form.rdbtnPontoJ.Checked = false;
        }

        //Função para calcular os parametros a serem exibidos
        public void calcularParametro() {
            Boolean ordemParametroCorreta = true;
            formCalculoParametros calculo = new formCalculoParametros();
            
            //Verifica se todos os parametros foram setados
            for (int i = 0; i < parametros.Length; i++)
            {
                if (parametros[i] == 0)
                {
                    ordemParametroCorreta = false;
                    MessageBox.Show("Marque o "+nomeParametros[i]);
                    break;
                }
            }

            //Verifica se a ordem dos parametros esta correta
            if (ordemParametroCorreta)
            {
                for (int i = 1; i < parametros.Length; i++)
                {
                    if (parametros[i - 1] >= parametros[i])
                    {
                        ordemParametroCorreta = false;
                        MessageBox.Show("O " + nomeParametros[i - 1] + " deve ser marcado antes do " + nomeParametros[i]);
                        break;
                    }
                }
            }

            if (ordemParametroCorreta) {
                int iniP = parametros[0];
                int fimP = parametros[1];
                int iniQRS = parametros[2];
                int apiR1 = parametros[3];
                int fimQRS = parametros[4];
                int pontoJ = parametros[5];
                int iniT = parametros[6];
                int fimT= parametros[7];
                int apiR2 = parametros[8];
                
                //Efetua o cálculo dos parametros propriamente ditos
                double duracaoP = (double)(fimP - iniP) / 960; //FimP - IniP
                double intervaloPR = (double)(iniQRS - iniP) / 960; //IniQRS - IniP
                double intervaloQRS = (double)(fimQRS - iniQRS) / 960; //FimQRS - IniQRS
                double intervaloST = (double)(iniT - pontoJ) / 960; //IniT - PontoJ
                double intervaloQT = (double)(fimT - iniQRS) / 960; //FimT - IniQRS
                double intervaloRR = (double)(apiR2 - apiR1) / 960; //ApiR2 - ApiR1
                double intervaloQTc = (double)intervaloQT / Math.Sqrt(intervaloRR); ; //IntervaloQT / Sqr(IntervaloRR)
                double duraçãoT = (double)(fimT - iniT) / 960; //FimT - IniT

                
                double mediaFimPIniQRS = 0;
                int delta = iniQRS - fimP;
                for (int i = fimP; i <= iniQRS; i++){
                    mediaFimPIniQRS = mediaFimPIniQRS + saidaFiltro[i];
                }
                 
                mediaFimPIniQRS = mediaFimPIniQRS / delta;

                double mediaST = 0;
                delta = iniT * amostrasPorSeg - pontoJ;
                for (int i = pontoJ; i<=iniT;i++){
                    mediaST = mediaST + saidaFiltro[i];
                }

                mediaST = mediaST / delta;

                double desnivelST = mediaFimPIniQRS - mediaST;

                //Seta os valores no formulário de parametros
                calculo.setDuracaoP(duracaoP);
                calculo.setIntervaloPR(intervaloPR);
                calculo.setIntervaloQRS(intervaloQRS);
                calculo.setIntervaloQT(intervaloQT);
                calculo.setIntervaloQTc(intervaloQTc);
                calculo.setIntervaloRR(intervaloRR);
                calculo.setAmplitudeP(0.0);
                calculo.setDesnivelST(desnivelST);
                calculo.setFrequencia(60 / intervaloRR);

                //Exibi o formulário de parametros
                calculo.Show();
            }

        }

        //Seta a posição do parametro e já converte essa posição para a escala de referência
        public void setParametro(int posicaoX) {
            double passoX = (double)form.pctboxDetalhada.Width / tamanhoDetalhe;
            int deslocamento = form.hscrbrRF.Value;

            if (form.rdbtnInicioOndaP.Checked) {
                parametros[0] = (int)(posicaoX / passoX) + deslocamento;
            }
            else if (form.rdbtnFimOndaP.Checked)
            {
                parametros[1] = (int)(posicaoX / passoX) + deslocamento;
            }
            else if (form.rdbtnInicioOndaQRS.Checked)
            {
                parametros[2] = (int)(posicaoX / passoX) + deslocamento;
            }
            else if (form.rdbtnApiceOndaR.Checked)
            {
                parametros[3] = (int)(posicaoX / passoX) + deslocamento;
            }
            else if (form.rdbtnFimOndaQRS.Checked)
            {
                parametros[4] = (int)(posicaoX / passoX) + deslocamento;
            }
            else if (form.rdbtnPontoJ.Checked)
            {
                parametros[5] = (int)(posicaoX / passoX) + deslocamento;
            }
            else if (form.rdbtnInicioOndaT.Checked)
            {
                parametros[6] = (int)(posicaoX / passoX) + deslocamento;
            }
            else if (form.rdbtnFimOndaT.Checked)
            {
                parametros[7] = (int)(posicaoX / passoX) + deslocamento;
            }
            else if (form.rdbtnApiceR.Checked)
            {
                parametros[8] = (int)(posicaoX / passoX) + deslocamento;
            }

            this.plotaDetalhes();
        }

        //Método que plota apenas as linha verticais referentes aos parametros
        public void plotaParametros()
        {
            double passoX = (double)form.pctboxDetalhada.Width / tamanhoDetalhe;
            double passoY = (double)form.pctboxDetalhada.Height / form.getMAX();
            int posicaoReta = 0;
            Graphics objGrafico = Graphics.FromImage(form.pctboxDetalhada.Image);
            Pen p = new Pen(Color.Gray, 0);
            p.Width = 1;
            for(int i=0 ; i<9; i++){
                //Verifica se a linha a ser impressa esta englobada pelo janelamento da amostra
                if (parametros[i] > form.hscrbrRF.Value && parametros[i] < form.hscrbrRF.Value+tamanhoDetalhe)
                {
                    //Detecta a cor da linha
                    p.Color = pctbxGrupoParametros[i].BackColor;
                    posicaoReta = (int)(passoX * (parametros[i] - form.hscrbrRF.Value));
                    objGrafico.DrawLine(p, posicaoReta, 0, posicaoReta, form.pctboxDetalhada.Height);
                }
            }
        }

		public void plotaQrs(Graphics objGrafico)
		{
		  	int sampleCount = 0;
			bdac.ResetBDAC();
			int j=0;
			int[] dTime = new int[50];
			
			double passoX = (double)form.pctboxDetalhada.Width / tamanhoDetalhe;
			Pen p = new Pen(Color.White, 1);
			Pen p2 = new Pen(Color.Red,1);
			
			int inicioImpressao = form.hscrbrRF.Value; 
			int posicaoReta = 0;
			
			int d0 = 0;
			int d1 = 0;
			int d2 = 0;
			
			QrsFilt filt = new QrsFilt();
			DTW dtw = null;
      		 int DetectionTime = 0;
			for (int i = 0; i < amostrasDetalhada.Length-1; i++)
            {
				 ++sampleCount;
				int fDatum = filt.filter(amostrasDetalhada[i]);
				int delay = bdac.BeatDetect(fDatum,i);
               		
                if (delay!= 0)
                {
					Console.Write("\n-------------- " + DetectionTime.ToString() +"::01");
                    DetectionTime = sampleCount - delay;
					Console.Write("\n-------------- " + DetectionTime.ToString() +"::02");
					int OffSetDetectionTime = detectOffSet ( DetectionTime);
					int OnSetDetectionTime = detectOnSet (DetectionTime);
					
					if(OffSetDetectionTime-OnSetDetectionTime > 30){
					
					if(d1!=0 && d0 ==0){
						 referencia = ArrayUtil.getSubArray(amostrasDetalhada,d2,DetectionTime);
						dtw = new DTW(referencia);
					}
					
					d0 = d1;
					d1 = d2;
					d2 = DetectionTime;
					
					if(d0 != 0){						
						listaParametros.Add(new BeatParameters(ArrayUtil.getSubArray(amostrasDetalhada,d0,d2),d1-d0));
						int [] amostra = ArrayUtil.getSubArray(amostrasDetalhada,d1,d2);
						Console.Write("-------------- "+amostra.Length);
						dtw.calcularDistancia(amostra);
						}
					
					
					posicaoReta = (int)(passoX * (DetectionTime - form.hscrbrRF.Value));
                    objGrafico.DrawLine(p, posicaoReta, 0, posicaoReta, form.pctboxDetalhada.Height);
					posicaoReta = (int)(passoX * (OffSetDetectionTime - form.hscrbrRF.Value));
					objGrafico.DrawLine(p2, posicaoReta, 0, posicaoReta, form.pctboxDetalhada.Height);
					posicaoReta = (int)(passoX * (OnSetDetectionTime - form.hscrbrRF.Value));
					objGrafico.DrawLine(p2, posicaoReta, 0, posicaoReta, form.pctboxDetalhada.Height);
					
					
					}
					
					
                } 
            }
			
		}

		public int detectOffSet ( int Dtime)
		{
			
			while(amostrasDetalhada[Dtime]>=amostrasDetalhada[Dtime+1]){
			      Dtime++;
		//		Console.Write(amostrasDetalhada[Dtime].ToString()+"//");
			}
			return Dtime;
		}
		
		public int detectOnSet (int Dtime)
		{
			while(amostrasDetalhada[Dtime]<amostrasDetalhada[Dtime-1])
			      Dtime--;
			while(amostrasDetalhada[Dtime]>=amostrasDetalhada[Dtime-1])
				Dtime--;
			return Dtime;
		}

		
		
		public void CalculaParametros(int d0,int d1,int d2){
			BeatParameters batimento =  new BeatParameters();
			
			int integral=0, area=0, min=0, max = 0;
			int sample=0;
			int baseSample = amostrasDetalhada[3*(d1-d0)/5];
			int normSample = 0;
			for(int i=d0+3*(d1-d0)/5;i<d1+2*(d2-d1)/5;i++){
					sample = amostrasDetalhada[i];
				if(sample<min)
					min = sample;
				if(sample>max)
					max = sample;
				normSample = sample - baseSample;
				integral+=(normSample);
				if(normSample<0)
					normSample*=-1;
				area+=normSample;
			}
			int onIndex = detectOffSet(d1);
			int offIndex = detectOnSet(d1);
			
			batimento.QRSDuration = onIndex - offIndex;
			batimento.Offset=amostrasDetalhada[offIndex];
			batimento.Onset=amostrasDetalhada[onIndex];
			batimento.Area = area;
			batimento.Integral = integral;
			batimento.Maximum = max;
			batimento.Minimum = min;
			batimento.RRInterval = d2-d1;
			batimento.PreviousRRInterval = d1- d0;
			
			listaParametros.Add(batimento);
		//	Console.Write("\nEu estou aqui olha eu aqui!!!\n");
		}
        //Imprime a grade
        public void plotaGrade()
        {
            double passoX, passoY;
            passoY = 200 * ganhoDetalhe *(double)form.pctboxDetalhada.Height / form.getMAX();
            passoX = form.pctboxDetalhada.Width/(tamanhoDetalhe/960);
            Graphics objGrafico = Graphics.FromImage(form.pctboxDetalhada.Image);
            Color corGrade = Color.FromArgb(255, 51, 00, 00);
            Pen p = new Pen(corGrade, 0);
            p.Width = 1;
            //Plota linhas verticais
            for (int i = 0; i < form.pctboxDetalhada.Width; i = i + (int)passoX) {
                objGrafico.DrawLine(p, i, 0, i, form.pctboxDetalhada.Height);    
            }
            //Plota linha horizontais
            for (int i = 0; i < form.pctboxDetalhada.Height; i = i + (int)passoY)
            {
                objGrafico.DrawLine(p, 0, i, form.pctboxDetalhada.Width, i);
            }
			
        }

        //Imprime a amostra já com o janelamento
        public void plotaDetalhes()
        {
            double passoX = (double)form.pctboxDetalhada.Width / tamanhoDetalhe;
            double passoY = (double)form.pctboxDetalhada.Height / form.getMAX();
            int refY = form.pctboxDetalhada.Height - 20;
            //Infere posição da impressão aparti da posição do scroll
            int inicioImpressao = form.hscrbrRF.Value; 

            Pen p = new Pen(Color.Green, 0);
            Pen p2 = new Pen(Color.Red, 0);
            Pen p3 = new Pen(Color.Yellow, 0);

            //As variaveis que terminam com 1 guardaram os valores atuais
            //Variáveis que terminam com 2 guardaram os valores anteriores
            int x1, x2, y1, y2;
            int x12, x22, y12, y22;
            int x13, x23, y13, y23;

            Bitmap objBMP = new Bitmap(form.pctboxDetalhada.Width, form.pctboxDetalhada.Height);
            form.pctboxDetalhada.Image = objBMP;
            this.plotaGrade();
            this.plotaParametros();

            Graphics objGrafico;
            objGrafico = Graphics.FromImage(objBMP);

            //Resta o valores iniciais
            x1 = y1 = 0;
            x12 = y12 = 0;
            x13 = y13 = 0;

            for (int i = inicioImpressao; i < inicioImpressao+tamanhoDetalhe; i++)
            {
                //Imprime dados com a filtragem selecionada
                x2 = (int)((i - inicioImpressao) * passoX);
                y2 = (int)((refY - ganhoDetalhe * amostrasDetalhadaFiltrada[i] * passoY));
                objGrafico.DrawLine(p, x1, y1, x2, y2);
                x1 = x2;
                y1 = y2;

                //Imprime dados sem filtragem
                if (form.chkbxSinalSemFiltragem.Checked) {
                    x22 = (int)((i - inicioImpressao) * passoX);
                    y22 = (int)((refY - ganhoDetalhe * amostrasDetalhada[i] * passoY));
                    objGrafico.DrawLine(p2, x12, y12, x22, y22);
                    x12 = x22;
                    y12 = y22;                    
                }

                //Imprime dados com potencial tardio
                if (form.rdbtnPotenciaisTardios.Checked)
                {
                    x23 = (int)((i - inicioImpressao) * passoX);
                    y23 = (int)((refY - ganhoDetalhe * amostrasDetalhadaPotenciaTardios[i] * passoY));
                    objGrafico.DrawLine(p3, x13, y13, x23, y23);
                    x13 = x23;
                    y13 = y23;
                }
            }
			plotaQrs(objGrafico);
            form.pctboxDetalhada.Refresh();
        }


        public void scroll()
        {
            this.plotaDetalhes();
        }

        public void setTamanhoDetalhe(int tamanhoDetalhe) 
        {
            this.tamanhoDetalhe = tamanhoDetalhe;
            this.plotaDetalhes();
        }

        public void setGanhoDetalhe(double ganhoDetalhe)
        {
            this.ganhoDetalhe = ganhoDetalhe;
            this.plotaDetalhes();
        }


//----------------------------------Filtros------------------------------------

        public void semFiltro() {
            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
                amostrasDetalhadaFiltrada[i] = amostrasDetalhada[i];
            }
            this.plotaDetalhes();
        }

        public void filtro60hz() { 
            int j;

            for (int i = 0;i<tamanhoMaximoDetalhe;i++){
               entradaFiltro[i] = amostrasDetalhada[i];
            }

            this.filtro60MediaCaminhante();

            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
               entradaFiltro[i] = amostrasDetalhada[i] - saidaFiltro[i];
               senoidinhaRuidosa[i] = entradaFiltro[i];
            }

            this.filtroFIR1PassaSo60();

            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
                j = tamanhoMaximoDetalhe - i - 1;
               entradaFiltro[i] = saidaFiltro[j];
            }

            this.filtroFIR1PassaSo60();

            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
                j = tamanhoMaximoDetalhe - i - 1;
               senoidinha60[i] = saidaFiltro[j];
            }

            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
               entradaFiltro[i] = senoidinhaRuidosa[i];
            }

            this.filtroFIR1PassaSo120();

            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
                j = tamanhoMaximoDetalhe - i - 1;
               entradaFiltro[i] = saidaFiltro[j];
            }

            this.filtroFIR1PassaSo120();

            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
                j = tamanhoMaximoDetalhe - i - 1;
               senoidinha120[i] = saidaFiltro[j];
            }

            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
               entradaFiltro[i] = senoidinhaRuidosa[i];
            }

            this.filtroFIR1PassaSo180();

            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
                j = tamanhoMaximoDetalhe - i - 1;
               entradaFiltro[i] = saidaFiltro[j];
            }

            this.filtroFIR1PassaSo180();

            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
                j = tamanhoMaximoDetalhe - i - 1;
               senoidinha180[i] = saidaFiltro[j];
            }

            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
               senoidinha60eHarm[i] = 0.9 * senoidinha60[i] + senoidinha120[i] + senoidinha180[i];
            }


            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
                amostrasDetalhadaFiltrada[i] = amostrasDetalhada[i] - (int)senoidinha60eHarm[i];
            }

            this.plotaDetalhes();
        }
        
        public void filtroPassaBaixo250hz() //passa baixa de 250hz
        {
            int j;

            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
               entradaFiltro[i] = amostrasDetalhada[i];
            }

            this.filtro60MediaCaminhante();

            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
               entradaFiltro[i] = amostrasDetalhada[i] - saidaFiltro[i];
               senoidinhaRuidosa[i] = entradaFiltro[i];
            }

            this.filtroFIR1PassaSo60();

            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
                j = tamanhoMaximoDetalhe - i - 1;
               entradaFiltro[i] = saidaFiltro[j];
            }

            this.filtroFIR1PassaSo60();

            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
                j = tamanhoMaximoDetalhe - i - 1;
               senoidinha60[i] = saidaFiltro[j];
            }

            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
               entradaFiltro[i] = senoidinhaRuidosa[i];
            }

            this.filtroFIR1PassaSo120();

            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
                j = tamanhoMaximoDetalhe - i - 1;
               entradaFiltro[i] = saidaFiltro[j];
            }

            this.filtroFIR1PassaSo120();

            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
                j = tamanhoMaximoDetalhe - i - 1;
               senoidinha120[i] = saidaFiltro[j];
            }

            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
               entradaFiltro[i] = senoidinhaRuidosa[i];
            }

            this.filtroFIR1PassaSo180();

            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
                j = tamanhoMaximoDetalhe - i - 1;
               entradaFiltro[i] = saidaFiltro[j];
            }

            this.filtroFIR1PassaSo180();

            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
                j = tamanhoMaximoDetalhe - i - 1;
               senoidinha180[i] = saidaFiltro[j];
            }

            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
               senoidinha60eHarm[i] = 0.9 * senoidinha60[i] + senoidinha120[i] + senoidinha180[i];
            }


            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
               entradaFiltro[i] = amostrasDetalhada[i] - senoidinha60eHarm[i];
            }

            this.filtroFIR1Low250();

            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
                j = tamanhoMaximoDetalhe - i - 1;
               entradaFiltro[i] = saidaFiltro[j];
            }

            this.filtroFIR1Low250();

            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
                j = tamanhoMaximoDetalhe - i - 1;
               amostrasDetalhadaFiltrada[i] = (int)saidaFiltro[j];
            }

            //this.selecionaDadosValidos();
            this.plotaDetalhes();
        }

        public void filtroPassaBaixo100hz()   //corta 60hz e passa baixa de 100hz
        {
            int j;

            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
                entradaFiltro[i] = amostrasDetalhada[i];
            }

            this.filtro60MediaCaminhante();

            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
                entradaFiltro[i] = amostrasDetalhada[i] - saidaFiltro[i];
                senoidinhaRuidosa[i] = entradaFiltro[i];
            }

            this.filtroFIR1Passaso60();

            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
                j = tamanhoMaximoDetalhe - i - 1;
                entradaFiltro[i] = saidaFiltro[j];
            }

            this.filtroFIR1Passaso60();

            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
                j = tamanhoMaximoDetalhe - i - 1;
                senoidinha60[i] = saidaFiltro[j];
            }

            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
                entradaFiltro[i] = senoidinhaRuidosa[i];
            }

            this.filtroFIR1Passaso120();

            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
                j = tamanhoMaximoDetalhe - i - 1;
                entradaFiltro[i] = saidaFiltro[j];
            }

            this.filtroFIR1Passaso120();

            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
                j = tamanhoMaximoDetalhe - i - 1;
                senoidinha120[i] = saidaFiltro[j];
            }

            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
                entradaFiltro[i] = senoidinhaRuidosa[i];
            }

            this.filtroFIR1Passaso180();

            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
                j = tamanhoMaximoDetalhe - i - 1;
                entradaFiltro[i] = saidaFiltro[j];
            }

            this.filtroFIR1Passaso180();

            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
                j = tamanhoMaximoDetalhe - i - 1;
                senoidinha180[i] = saidaFiltro[j];
            }

            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
                senoidinha60eHarm[i] = 0.9 * senoidinha60[i] + senoidinha120[i] + senoidinha180[i];
            }

            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
                entradaFiltro[i] = amostrasDetalhada[i] - senoidinha60eHarm[i];
            }

            this.filtroFIR1Low100();

            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
                j = tamanhoMaximoDetalhe - i - 1;
                entradaFiltro[i] = saidaFiltro[j];
            }

            this.filtroFIR1Low100();

            for (int i = 0; i < tamanhoMaximoDetalhe; i++)
            {
                j = tamanhoMaximoDetalhe - i - 1;
                amostrasDetalhadaFiltrada[i] = (int)saidaFiltro[j];
            }

            //this.selecionaDadosValidos();
            this.plotaDetalhes();
        }

        public void potenciaisTardios(){ 
            int j;

            //Primeiro calcula o sinal médio que é o filtro média caminhante corta 60hz

            for (int i = 0; i < tamanhoMaximoDetalhe; i++){
               entradaFiltro[i] = amostrasDetalhada[i];
            }

            this.filtro60MediaCaminhante();

            for (int i = 0; i < tamanhoMaximoDetalhe; i++){
               entradaFiltro[i] = amostrasDetalhada[i] - saidaFiltro[i];
               senoidinhaRuidosa[i] = entradaFiltro[i]; //ruido de 60hz + potenciais tardios etc...
            }

            //separa os 60hz

            this.filtroFIR1Passaso60();

            for (int i = 0; i < tamanhoMaximoDetalhe; i++){
                j = tamanhoMaximoDetalhe - i - 1; //vira
               entradaFiltro[i] = saidaFiltro[j];
            }

            this.filtroFIR1Passaso60();

            for (int i = 0; i < tamanhoMaximoDetalhe; i++){
                j = tamanhoMaximoDetalhe - i - 1; //desvira
               senoidinha60[i] = saidaFiltro[j];
            }

            //separa os 120hz

            for (int i = 0; i < tamanhoMaximoDetalhe; i++){
               entradaFiltro[i] = senoidinhaRuidosa[i];
            }

            this.filtroFIR1Passaso120();

            for (int i = 0; i < tamanhoMaximoDetalhe; i++){
                j = tamanhoMaximoDetalhe - i - 1;
               entradaFiltro[i] = saidaFiltro[j];
            }

            this.filtroFIR1Passaso120();

            for (int i = 0; i < tamanhoMaximoDetalhe; i++){
                j = tamanhoMaximoDetalhe - i - 1;
               senoidinha120[i] = saidaFiltro[j];
            }

            //separa os 180hz

            for (int i = 0; i < tamanhoMaximoDetalhe; i++){
               entradaFiltro[i] = senoidinhaRuidosa[i];
            }

            this.filtroFIR1Passaso180();

            for (int i = 0; i < tamanhoMaximoDetalhe; i++){
                j = tamanhoMaximoDetalhe - i - 1;
               entradaFiltro[i] = saidaFiltro[j];
            }

            this.filtroFIR1Passaso180();

            for (int i = 0; i < tamanhoMaximoDetalhe; i++){
                j = tamanhoMaximoDetalhe - i - 1;
               senoidinha180[i] = saidaFiltro[j];
            }

            for (int i = 0; i < tamanhoMaximoDetalhe; i++){
               senoidinha60eHarm[i] = 0.9 * senoidinha60[i] + senoidinha120[i] + senoidinha180[i];
            }


            for (int i = 0; i < tamanhoMaximoDetalhe; i++){
               entradaFiltro[i] = amostrasDetalhada[i] - senoidinha60eHarm[i];
            }

            this.filtroFIR1Low100();

            for (int i = 0; i < tamanhoMaximoDetalhe; i++){
                j = tamanhoMaximoDetalhe - i - 1;
               entradaFiltro[i] = saidaFiltro[j];
            }

            this.filtroFIR1Low100();

            for (int i = 0; i < tamanhoMaximoDetalhe; i++){
                j = tamanhoMaximoDetalhe - i - 1;
               amostrasDetalhadaPotenciaTardios[i] = (int)saidaFiltro[j]; //guarda o sinal filtrado sem 60 e
            }                                   // harmonicas e sem acima de 100hz

            //Agora a banda 80-250hz

            for (int i = 0; i < tamanhoMaximoDetalhe; i++){
                entradaFiltro[i] = amostrasDetalhada[i] - amostrasDetalhadaPotenciaTardios[i] - senoidinha60eHarm[i]; //pega só os potenciais tardios
            }

            //Call FiltroFIR1PassaBanda80a250

            for (int i = 0; i < tamanhoMaximoDetalhe; i++){
                j = tamanhoMaximoDetalhe - i - 1;
                //entradaFiltro[i] = saidaFiltro[j];
            }

            //this.filtroFIR1PassaBanda80a250

            for (int i = 0; i < tamanhoMaximoDetalhe; i++){
               j = tamanhoMaximoDetalhe - i;
                //entradaFiltro[i] = saidaFiltro[j];
            }

            for (int i = 0; i < tamanhoMaximoDetalhe; i++){
                amostrasDetalhadaFiltrada[i] = (int)(3 * entradaFiltro[i]) + amostrasDetalhadaPotenciaTardios[i];
            }

            //this.selecionaDadosValidos();
            this.plotaDetalhes();
        }


        private void filtro60MediaCaminhante() //chupetinha: média caminhante de um ciclo completo e exato de 60hz
        {
            double soma;

            for (int i = 9; i <= tamanhoMaximoDetalhe - 9; i++)
            {
                soma = 0;
                // For j = i - 6 To i + 7   ' teste onde o resultado muda muito para pior!!!!
                //For j = i - 8 To i + 9
                for (int j = i - 7; j <= i + 8; j++)
                {
                    soma = soma + entradaFiltro[j];
                }
                saidaFiltro[i] = soma / 16;
            }
        }

        private void filtroFIR1PassaSo60()
        {

            double soma;

            // B=FIR1(17,[2*58/960 2*62/960])          ' passa 60hz

            B60[1] = -0.0169;
            B60[2] = -0.0234;
            B60[3] = -0.0358;
            B60[4] = -0.0401;
            B60[5] = -0.0209;
            B60[6] = 0.028;
            B60[7] = 0.0979;
            B60[8] = 0.1669;
            B60[9] = 0.2098;
            B60[10] = B60[9];
            B60[11] = B60[8];
            B60[12] = B60[7];
            B60[13] = B60[6];
            B60[14] = B60[5];
            B60[15] = B60[4];
            B60[16] = B60[3];
            B60[17] = B60[2];
            B60[18] = B60[1];

            for (int i = 19; i < tamanhoMaximoDetalhe; i++)
            {
                soma = 0;
                soma = soma + B60[1] * entradaFiltro[i - 1];
                soma = soma + B60[2] * entradaFiltro[i - 2];
                soma = soma + B60[3] * entradaFiltro[i - 3];
                soma = soma + B60[4] * entradaFiltro[i - 4];
                soma = soma + B60[5] * entradaFiltro[i - 5];
                soma = soma + B60[6] * entradaFiltro[i - 6];
                soma = soma + B60[7] * entradaFiltro[i - 7];
                soma = soma + B60[8] * entradaFiltro[i - 8];
                soma = soma + B60[9] * entradaFiltro[i - 9];
                soma = soma + B60[10] * entradaFiltro[i - 10];
                soma = soma + B60[11] * entradaFiltro[i - 11];
                soma = soma + B60[12] * entradaFiltro[i - 12];
                soma = soma + B60[13] * entradaFiltro[i - 13];
                soma = soma + B60[14] * entradaFiltro[i - 14];
                soma = soma + B60[15] * entradaFiltro[i - 15];
                soma = soma + B60[16] * entradaFiltro[i - 16];
                soma = soma + B60[17] * entradaFiltro[i - 17];
                soma = soma + B60[18] * entradaFiltro[i - 18];

                saidaFiltro[i] = soma;
            }
        }

        private void filtroFIR1PassaSo120()
        {

            double soma;

            //B=FIR1(16,[2*116/960 2*124/960])          ' passa 120hz

            B60[1] = 0.0181;
            B60[2] = 0.0184;
            B60[3] = 0;
            B60[4] = -0.0584;
            B60[5] = -0.1227;
            B60[6] = -0.1151;
            B60[7] = 0;
            B60[8] = 0.1553;
            B60[9] = 0.2276;
            B60[10] = B60[8];
            B60[11] = B60[7];
            B60[12] = B60[6];
            B60[13] = B60[5];
            B60[14] = B60[4];
            B60[15] = B60[3];
            B60[16] = B60[2];
            B60[17] = B60[1];

            for (int i = 18; i < tamanhoMaximoDetalhe; i++)
            {
                soma = 0;
                soma = soma + B60[1] * entradaFiltro[i - 1];
                soma = soma + B60[2] * entradaFiltro[i - 2];
                soma = soma + B60[3] * entradaFiltro[i - 3];
                soma = soma + B60[4] * entradaFiltro[i - 4];
                soma = soma + B60[5] * entradaFiltro[i - 5];
                soma = soma + B60[6] * entradaFiltro[i - 6];
                soma = soma + B60[7] * entradaFiltro[i - 7];
                soma = soma + B60[8] * entradaFiltro[i - 8];
                soma = soma + B60[9] * entradaFiltro[i - 9];
                soma = soma + B60[10] * entradaFiltro[i - 10];
                soma = soma + B60[11] * entradaFiltro[i - 11];
                soma = soma + B60[12] * entradaFiltro[i - 12];
                soma = soma + B60[13] * entradaFiltro[i - 13];
                soma = soma + B60[14] * entradaFiltro[i - 14];
                soma = soma + B60[15] * entradaFiltro[i - 15];
                soma = soma + B60[16] * entradaFiltro[i - 16];
                soma = soma + B60[17] * entradaFiltro[i - 17];

                saidaFiltro[i] = soma;
            }
        }

        private void filtroFIR1PassaSo180()
        {

            double soma;

            // B=FIR1[16,[2*176/960 2*186/960]]          ' passa 180

            B60[1] = -0.0179;
            B60[2] = -0.0099;
            B60[3] = 0.0343;
            B60[4] = 0.0762;
            B60[5] = 0;
            B60[6] = -0.1504;
            B60[7] = -0.1393;
            B60[8] = 0.0842;
            B60[9] = 0.2279;
            B60[10] = B60[8];
            B60[11] = B60[7];
            B60[12] = B60[6];
            B60[13] = B60[5];
            B60[14] = B60[4];
            B60[15] = B60[3];
            B60[16] = B60[2];
            B60[17] = B60[1];


            for (int i = 18; i < tamanhoMaximoDetalhe; i++)
            {
                soma = 0;
                soma = soma + B60[1] * entradaFiltro[i - 1];
                soma = soma + B60[2] * entradaFiltro[i - 2];
                soma = soma + B60[3] * entradaFiltro[i - 3];
                soma = soma + B60[4] * entradaFiltro[i - 4];
                soma = soma + B60[5] * entradaFiltro[i - 5];
                soma = soma + B60[6] * entradaFiltro[i - 6];
                soma = soma + B60[7] * entradaFiltro[i - 7];
                soma = soma + B60[8] * entradaFiltro[i - 8];
                soma = soma + B60[9] * entradaFiltro[i - 9];
                soma = soma + B60[10] * entradaFiltro[i - 10];
                soma = soma + B60[11] * entradaFiltro[i - 11];
                soma = soma + B60[12] * entradaFiltro[i - 12];
                soma = soma + B60[13] * entradaFiltro[i - 13];
                soma = soma + B60[14] * entradaFiltro[i - 14];
                soma = soma + B60[15] * entradaFiltro[i - 15];
                soma = soma + B60[16] * entradaFiltro[i - 16];
                soma = soma + B60[17] * entradaFiltro[i - 17];
                saidaFiltro[i] = soma;
            }
        }

        private void filtroFIR1Low250()
        {

            double soma;

            //B=FIR1[16,2*250/960]          ' passa baixa 250

            B60[1] = 0.0016;
            B60[2] = -0.0047;
            B60[3] = -0.0044;
            B60[4] = 0.0219;
            B60[5] = 0.0111;
            B60[6] = -0.0745;
            B60[7] = -0.018;
            B60[8] = 0.3065;
            B60[9] = 0.5208;
            B60[10] = B60[8];
            B60[11] = B60[7];
            B60[12] = B60[6];
            B60[13] = B60[5];
            B60[14] = B60[4];
            B60[15] = B60[3];
            B60[16] = B60[2];
            B60[17] = B60[1];

            for (int i = 18; i < tamanhoMaximoDetalhe; i++)
            {
                soma = 0;
                soma = soma + B60[1] * entradaFiltro[i - 1];
                soma = soma + B60[2] * entradaFiltro[i - 2];
                soma = soma + B60[3] * entradaFiltro[i - 3];
                soma = soma + B60[4] * entradaFiltro[i - 4];
                soma = soma + B60[5] * entradaFiltro[i - 5];
                soma = soma + B60[6] * entradaFiltro[i - 6];
                soma = soma + B60[7] * entradaFiltro[i - 7];
                soma = soma + B60[8] * entradaFiltro[i - 8];
                soma = soma + B60[9] * entradaFiltro[i - 9];
                soma = soma + B60[10] * entradaFiltro[i - 10];
                soma = soma + B60[11] * entradaFiltro[i - 11];
                soma = soma + B60[12] * entradaFiltro[i - 12];
                soma = soma + B60[13] * entradaFiltro[i - 13];
                soma = soma + B60[14] * entradaFiltro[i - 14];
                soma = soma + B60[15] * entradaFiltro[i - 15];
                soma = soma + B60[16] * entradaFiltro[i - 16];
                soma = soma + B60[17] * entradaFiltro[i - 17];

                saidaFiltro[i] = soma;
            }
        }

        private void filtroFIR1Passaso60()
        {

            double soma;

            // B=FIR1[17,[2*58/960 2*62/960]]          ' passa 60hz

            B60[1] = -0.0169;
            B60[2] = -0.0234;
            B60[3] = -0.0358;
            B60[4] = -0.0401;
            B60[5] = -0.0209;
            B60[6] = 0.028;
            B60[7] = 0.0979;
            B60[8] = 0.1669;
            B60[9] = 0.2098;
            B60[10] = B60[9];
            B60[11] = B60[8];
            B60[12] = B60[7];
            B60[13] = B60[6];
            B60[14] = B60[5];
            B60[15] = B60[4];
            B60[16] = B60[3];
            B60[17] = B60[2];
            B60[18] = B60[1];

            for (int i = 18; i < tamanhoMaximoDetalhe; i++)
            {
                soma = 0;
                soma = soma + B60[1] * entradaFiltro[i - 1];
                soma = soma + B60[2] * entradaFiltro[i - 2];
                soma = soma + B60[3] * entradaFiltro[i - 3];
                soma = soma + B60[4] * entradaFiltro[i - 4];
                soma = soma + B60[5] * entradaFiltro[i - 5];
                soma = soma + B60[6] * entradaFiltro[i - 6];
                soma = soma + B60[7] * entradaFiltro[i - 7];
                soma = soma + B60[8] * entradaFiltro[i - 8];
                soma = soma + B60[9] * entradaFiltro[i - 9];
                soma = soma + B60[10] * entradaFiltro[i - 10];
                soma = soma + B60[11] * entradaFiltro[i - 11];
                soma = soma + B60[12] * entradaFiltro[i - 12];
                soma = soma + B60[13] * entradaFiltro[i - 13];
                soma = soma + B60[14] * entradaFiltro[i - 14];
                soma = soma + B60[15] * entradaFiltro[i - 15];
                soma = soma + B60[16] * entradaFiltro[i - 16];
                soma = soma + B60[17] * entradaFiltro[i - 17];
                soma = soma + B60[18] * entradaFiltro[i - 18];

                saidaFiltro[i] = soma;
            }
        }

        private void filtroFIR1Passaso120()
        {

            double soma;

            //B=FIR1[16,[2*116/960 2*124/960]]          ' passa 120hz

            B60[1] = 0.0181;
            B60[2] = 0.0184;
            B60[3] = 0;
            B60[4] = -0.0584;
            B60[5] = -0.1227;
            B60[6] = -0.1151;
            B60[7] = 0;
            B60[8] = 0.1553;
            B60[9] = 0.2276;
            B60[10] = B60[8];
            B60[11] = B60[7];
            B60[12] = B60[6];
            B60[13] = B60[5];
            B60[14] = B60[4];
            B60[15] = B60[3];
            B60[16] = B60[2];
            B60[17] = B60[1];



            for (int i = 18; i < tamanhoMaximoDetalhe; i++)
            {
                soma = 0;
                soma = soma + B60[1] * entradaFiltro[i - 1];
                soma = soma + B60[2] * entradaFiltro[i - 2];
                soma = soma + B60[3] * entradaFiltro[i - 3];
                soma = soma + B60[4] * entradaFiltro[i - 4];
                soma = soma + B60[5] * entradaFiltro[i - 5];
                soma = soma + B60[6] * entradaFiltro[i - 6];
                soma = soma + B60[7] * entradaFiltro[i - 7];
                soma = soma + B60[8] * entradaFiltro[i - 8];
                soma = soma + B60[9] * entradaFiltro[i - 9];
                soma = soma + B60[10] * entradaFiltro[i - 10];
                soma = soma + B60[11] * entradaFiltro[i - 11];
                soma = soma + B60[12] * entradaFiltro[i - 12];
                soma = soma + B60[13] * entradaFiltro[i - 13];
                soma = soma + B60[14] * entradaFiltro[i - 14];
                soma = soma + B60[15] * entradaFiltro[i - 15];
                soma = soma + B60[16] * entradaFiltro[i - 16];
                soma = soma + B60[17] * entradaFiltro[i - 17];

                saidaFiltro[i] = soma;
            }
        }

        private void filtroFIR1Passaso180()
        {

            double soma;

            //B=FIR1[16,[2*176/960 2*186/960]]          ' passa 180

            B60[1] = -0.0179;
            B60[2] = -0.0099;
            B60[3] = 0.0343;
            B60[4] = 0.0762;
            B60[5] = 0;
            B60[6] = -0.1504;
            B60[7] = -0.1393;
            B60[8] = 0.0842;
            B60[9] = 0.2279;
            B60[10] = B60[8];
            B60[11] = B60[7];
            B60[12] = B60[6];
            B60[13] = B60[5];
            B60[14] = B60[4];
            B60[15] = B60[3];
            B60[16] = B60[2];
            B60[17] = B60[1];

            for (int i = 18; i < tamanhoMaximoDetalhe; i++)
            {
                soma = 0;
                soma = soma + B60[1] * entradaFiltro[i - 1];
                soma = soma + B60[2] * entradaFiltro[i - 2];
                soma = soma + B60[3] * entradaFiltro[i - 3];
                soma = soma + B60[4] * entradaFiltro[i - 4];
                soma = soma + B60[5] * entradaFiltro[i - 5];
                soma = soma + B60[6] * entradaFiltro[i - 6];
                soma = soma + B60[7] * entradaFiltro[i - 7];
                soma = soma + B60[8] * entradaFiltro[i - 8];
                soma = soma + B60[9] * entradaFiltro[i - 9];
                soma = soma + B60[10] * entradaFiltro[i - 10];
                soma = soma + B60[11] * entradaFiltro[i - 11];
                soma = soma + B60[12] * entradaFiltro[i - 12];
                soma = soma + B60[13] * entradaFiltro[i - 13];
                soma = soma + B60[14] * entradaFiltro[i - 14];
                soma = soma + B60[15] * entradaFiltro[i - 15];
                soma = soma + B60[16] * entradaFiltro[i - 16];
                soma = soma + B60[17] * entradaFiltro[i - 17];

                saidaFiltro[i] = soma;
            }
        }

        private void filtroFIR1Low100()
        {

            double soma;

            //B=FIR1[16,2*100/960]          ' passa baixa 100

            B60[1] = -0.0028;
            B60[2] = -0.0052;
            B60[3] = -0.0081;
            B60[4] = -0.003;
            B60[5] = 0.0216;
            B60[6] = 0.0706;
            B60[7] = 0.1339;
            B60[8] = 0.1882;
            B60[9] = 0.2097;
            B60[10] = B60[8];
            B60[11] = B60[7];
            B60[12] = B60[6];
            B60[13] = B60[5];
            B60[14] = B60[4];
            B60[15] = B60[3];
            B60[16] = B60[2];
            B60[17] = B60[1];

            for (int i = 18; i < tamanhoMaximoDetalhe; i++)
            {
                soma = 0;
                soma = soma + B60[1] * entradaFiltro[i - 1];
                soma = soma + B60[2] * entradaFiltro[i - 2];
                soma = soma + B60[3] * entradaFiltro[i - 3];
                soma = soma + B60[4] * entradaFiltro[i - 4];
                soma = soma + B60[5] * entradaFiltro[i - 5];
                soma = soma + B60[6] * entradaFiltro[i - 6];
                soma = soma + B60[7] * entradaFiltro[i - 7];
                soma = soma + B60[8] * entradaFiltro[i - 8];
                soma = soma + B60[9] * entradaFiltro[i - 9];
                soma = soma + B60[10] * entradaFiltro[i - 10];
                soma = soma + B60[11] * entradaFiltro[i - 11];
                soma = soma + B60[12] * entradaFiltro[i - 12];
                soma = soma + B60[13] * entradaFiltro[i - 13];
                soma = soma + B60[14] * entradaFiltro[i - 14];
                soma = soma + B60[15] * entradaFiltro[i - 15];
                soma = soma + B60[16] * entradaFiltro[i - 16];
                soma = soma + B60[17] * entradaFiltro[i - 17];

                saidaFiltro[i] = soma;
            }
        }

    }
}
